<?php
/**
 *  后台菜单管理
*/

namespace app\admin\service;
use app\admin\model\RoleAuth;
use app\facade\Basic;
use app\admin\model\Menu as ModelMenu;
use app\admin\model\Role as ModelRole;
use think\facade\Db;

class Menu extends BaseService
{
    /**
     *  后台菜单列表
    */
    public function RoleMenu($param)
    {
        $where[] = ['is_del','=','0'];
        $where[] = ['status','=','1'];
        $where[] = ['type','in',[1,2,3]];



        if(empty($param['roles']) || $param['isadmin'] == 1) {

            $result = ModelMenu::where($where)->order('sort ESC,id ESC')->select();
            $data = $result->toArray();

        } else {

            $role_auth = RoleAuth::where('roleid','in',$param['roles'])->field('menuid')->select();
            if(!$role_auth){
                return Basic::data(1,'权限不存在');
            }

            $ids = [];
            foreach ($role_auth as $v) {
                $ids[] = $v['menuid'];
            }
            $ids2 = $this->recursionPid($ids);
            $pids = array_values(array_unique(array_merge($ids, $ids2)));
            $result = ModelMenu::where($where)->where('id','in',$pids)->order('sort ESC,id ESC')->select();
            $data = $result->toArray();
        }

        $data = $this->role_tree($data);
        return Basic::data(0,'ok',$data);
    }


    /**
     * 获取PID
     */
    public function recursionPid($ids)
    {
        $where[] = ['is_del', '=', '0'];
        $where[] = ['status', '=', '1'];
        $where[] = ['type', 'in', [1, 2]];
        $parent = ModelMenu::where($where)->where('id', 'in', $ids)->field('parent_id')->select();
        $parent_ids = [];
        if ($parent) {
            $data_ids = $parent->toArray();
            foreach ($data_ids as $key => $value) {
                if ($value['parent_id'] != 0) {
                    $parent_ids[] = $value['parent_id'];
                }
            }
        }

        $pids = array_values(array_unique($parent_ids));
        $result = array_unique(array_merge($ids, $parent_ids));
        if (count($pids) > 0) {
            $recursionPid = $this->recursionPid($pids);
            if ($recursionPid) {
                $result = array_unique(array_merge($result,$recursionPid));
            }
        }
        return $result;
    }



    /**
     *  权限菜单递归处理
     */
    function role_tree(array $data, $parent_id = 0) {
        $branch = [];
        foreach ($data as $value) {
            // 跳过 type=3 的数据
            if ($value['type'] == 3) {
                continue;
            }
            
            $element = [];
            $element['path'] = $value['url'];
            $element['component'] = $value['components'];
            $element['redirect'] = $value['redirect'];
            $element['name'] = $value['components_name'];
            $element['sort'] = $value['sort'];

            /* 菜单名称 */
            $meta['title'] = $value['name'];
            if (is_null($value['icon'])) {
                $meta['icon'] = "";
            } else {
                $meta['icon'] = $value['icon'];
            }

            $meta['activeMenu'] = $value['active_menu'];
            $meta['hidden'] = (bool) $value['is_hide'];
            $meta['alwaysShow'] = (bool) $value['is_display'];
            $meta['noCache'] = (bool) $value['is_alive'];
            $meta['breadcrumb'] = (bool) $value['is_multiple'];
            $meta['affix'] = false;
            $meta['noTagsView'] = false;
            $meta['canTo'] = true;
            $meta['permission'] = [];

            // 如果是菜单类型，收集所有子集的 btnkey
            if ($value['type'] == 2) {
                $childBtnKeys = $this->collectChildBtnKeys($data, $value['id']);
                if (!empty($childBtnKeys)) {
                    $meta['permission'] = $childBtnKeys;
                }
            }

            /* 菜单名称 */
            $element['meta'] = $meta;

            if ($value['parent_id'] == $parent_id) {
                $children = $this->role_tree($data, $value['id']);
                if ($children) {
                    array_multisort(array_column($children, 'sort'), SORT_ASC, $children);
                    $element['children'] = $children;
                }
                $branch[] = $element;
            }
        }

        return $branch;
    }

    /**
     * 收集子集的 btnkey
     */
    private function collectChildBtnKeys(array $data, $parent_id) {
        $btnKeys = [];
        foreach ($data as $item) {
            if ($item['parent_id'] == $parent_id) {
                // 如果是按钮类型（type=3）且有 btnkey
                if ($item['type'] == 3 && !empty($item['btnkey'])) {
                    $btnKeys[] = $item['btnkey'];
                }
                // 递归收集更深层级的按钮
                $childBtnKeys = $this->collectChildBtnKeys($data, $item['id']);
                if (!empty($childBtnKeys)) {
                    $btnKeys = array_merge($btnKeys, $childBtnKeys);
                }
            }
        }
        return array_unique($btnKeys);
    }


    /**
     *  菜单管理列表
    */
    public function list($param)
    {
        $where[] = ['type','in',[1,2]];
        $where[] = ['is_del','=','0'];
        $result = ModelMenu::where($where)->select();
        $data['list'] = $this->menu_tree($result->toArray());
        return Basic::data(0,'ok',$data);
    }

    /**
     *  菜单递归处理
    */
    function menu_tree(array $data, $parent_id = 0) {

        $branch = [];
        foreach ($data as $value) {
            $element = [];
            $element['id'] = $value['id'];
            $element['type'] = $value['type'];
            $element['parentId'] = $value['parent_id'];
            $element['path'] = $value['url'];
            $element['component'] = $value['components'];
            $element['redirect'] = $value['url'];
            $element['name'] = $value['components_name'];
            $element['status'] = $value['status'];
            $element['title'] = $value['name'];
            $element['sort'] = $value['sort'];

            /* 菜单名称 */
            $meta['title'] = $value['name'];
            if (is_null($value['icon'])) {
                $meta['icon'] = "";
            } else {
                $meta['icon'] = $value['icon'];
            }

            $meta['activeMenu'] = $value['active_menu'];

            $meta['hidden'] = (bool) $value['is_hide'];
            $meta['alwaysShow'] = (bool) $value['is_display'];
            $meta['noCache'] = (bool) $value['is_alive'];
            $meta['breadcrumb'] = (bool) $value['is_multiple'];
            $meta['affix'] = false;
            $meta['noTagsView'] = false;
            $meta['canTo'] = false;
            $meta['permission'] = [];

            /* 菜单名称 */
            $element['meta'] = $meta;

            /* 按钮权限 */
            if (!empty($value['permission'])) {
                $items = explode(',', $value['permission']);
                $permissionList = [];
                foreach ($items as $id => $item) {
                    list($label, $val) = explode(':', $item);
                    $permissionList[] = [
                        'id' => $id + 1,
                        'label' => $label,
                        'value' => $val,
                    ];
                }
                $element['permissionList'] = $permissionList;
            }

            if ($value['parent_id'] == $parent_id) {
                $children = $this->menu_tree($data, $value['id']);
                if ($children) {
                    $element['children'] = $children;
                }
                $branch[] = $element;
            }
        }

        array_multisort(array_column($branch, 'sort'), SORT_ASC, $branch);
        return $branch;
    }


    /**
     *  菜单详情
    */
    public function detail($param)
    {
        /* 修改 */
        $result = ModelMenu::with(['permission'=>function($query){
            $query->field('id,parent_id,type,name,route,method,sort,btnkey')->where('is_del',0)->where('type',3);
        },'parent'=>function($query){
            $query->field('id,parent_id,name');
        }])->where('id',$param['id'])->find();

        if(!$result){
            return Basic::data(1, '菜单不存在');
        }
        return Basic::data(0,'ok',$result);

    }

    /**
     *  创建菜单
    */
    public function save($param)
    {
        $insData = [];
        $insData['parent_id'] = $param['parent_id'];
        $insData['type'] = $param['type'];
        $insData['name'] = $param['name'];
        $insData['components'] = $param['components'];
        $insData['components_name'] = $param['components_name'];
        $insData['url'] = $param['url'];
        $insData['redirect'] = $param['redirect'];
        $insData['icon'] = $param['icon'];
        $insData['active_menu'] = $param['active_menu'];
        $insData['status'] = $param['status'];
        $insData['is_hide'] = $param['is_hide'];
        $insData['is_alive'] = $param['is_alive'];
        $insData['is_display'] = $param['is_display'];
        $insData['is_multiple'] = $param['is_multiple'];
        $insData['sort'] = $param['sort'];

        if(isset($param['id'])) {
            /* 修改 */
            $result = ModelMenu::where('id',$param['id'])->find();

            if(!$result){
                return Basic::data(1, '菜单不存在');
            }

            $insData['id'] = $param['id'];
            $insData['update_time'] = date("Y-m-d H:i:s",time());
            $insData['updater'] = $param['creator'];

            $result = ModelMenu::update($insData);

            if ( $result ) {
                return Basic::data(0, '更新成功');
            } else {
                return Basic::data(1, '更新失败');
            }

        } else {

            /* 创建 */
            $result = ModelMenu::where('name',$param['name'])->where('is_del','0')->find();

            if($result){
                return Basic::data(1, '菜单已存在');
            }

            $insData['create_time'] = date("Y-m-d H:i:s",time());
            $insData['creator'] = $param['creator'];
            $insData['update_time'] = null;
            $insData['updater'] = null;
            $insData['is_del'] = 0;


            Db::startTrans();

            try {

                $result = ModelMenu::create($insData);

                /* 批量添加权限按钮 */
                if ( $param['permission'] ) {

                    if ( !is_array( $param['permission'] ) ) {
                        return Basic::data(1,'删除失败');
                    }

                    foreach ( $param['permission'] as $value ) {
                        $insMenu[] = [
                            'type' => 3,
                            'creator' =>$param['creator'],
                            'create_time' => date("Y-m-d H:i:s",time()),
                            'btnkey' => $value['btnkey'],
                            'name' => $value['name'],
                            'parent_id' => $result->id,
                            'method' => $value['method'],
                            'route' => $value['route']
                        ];
                    }

                    ModelMenu::insertAll($insMenu);
                }

                Db::commit();

            } catch (\Exception $e) {

                Db::rollback();
                return Basic::data(1, '创建失败');

            }
            // todo 未获取到id
            $this->logger->logOperation([],'Menu','创建','创建菜单');
            return Basic::data(0, '创建成功');

        }
    }

    /**
     *  修改菜单
    */
    public function status($param)
    {
        $result = ModelMenu::where('id','in',$param['ids'])->select();
        if ( !$result ) {
            return Basic::data(1,'菜单不存在');
        }

        if ( count($param['ids']) != count($result) ) {
            return Basic::data(1,'菜单数量错误');
        }

        $result = ModelMenu::where('id','in',$param['ids'])->update([
            'status' => $param['status']
        ]);

        if ($result) {
            $this->logger->logOperation($param['ids'],'Menu','修改','修改菜单状态');
            return Basic::data(0, '状态更新成功');
        } else {
            return Basic::data(1, '状态更新失败');
        }
    }

    /**
     *  删除
    */
    public function delete($param)
    {

        $result = ModelMenu::where('id',$param['id'])->find();

        if ( !$result ) {
            return Basic::data(1,'菜单不存在');
        }

        if($result->is_del > 0) {
            return Basic::data(1, '已删除');
        }

        $parent_result = ModelMenu::where('parent_id',$param['id'])->where('is_del','0')->find();

        if ( $parent_result ) {
            return Basic::data(1, '存在子项目无法删除');
        }

        if ( !$result ) {
            return Basic::data(1, '菜单不存在');
        }

        Db::startTrans();
        try {

            $result->is_del = time();
            $result->update_time = date("Y-m-d H:i:s",time());
            $result->updater = $param['creator'];

            $result->save();
            RoleAuth::where('menuid',$param['id'])->delete();

            Db::commit();

        } catch (\Exception $e) {

            Db::rollback();
            return Basic::data(1,'删除失败');
        }
        $this->logger->logOperation($param['id'],'Menu','删除','删除菜单');
        return Basic::data(0, '删除成功');
    }

}
